package com.google.code.vannevar.server.framework;

import static com.google.gwt.user.server.rpc.RPC.decodeRequest;
import static com.google.gwt.user.server.rpc.RPC.encodeResponseForFailure;
import static com.google.gwt.user.server.rpc.RPC.invokeAndEncodeResponse;

import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.server.rpc.RPCRequest;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.google.inject.Injector;

public final class GuiceServlet extends RemoteServiceServlet {

    private static final long serialVersionUID = 6115386339715841565L;

    @Override
    public String processCall(String payload) throws SerializationException {

        String result = null;
        RPCRequest request = decodeRequest(payload);
        
        try {

            result = invokeAndEncodeResponse(
                    getService(request.getMethod().getDeclaringClass()),
                    request.getMethod(), request.getParameters(),
                    request.getSerializationPolicy());

        } catch (IncompatibleRemoteServiceException exception) {
            
            getServletContext().log("Incompatible Remote Service.", exception);
            result = encodeResponseForFailure(request.getMethod(), exception);
        }
        
        return result;
    }

    private Injector getInjector() {
        
        return (Injector) getServletContext().getAttribute("injector");
    }

    @SuppressWarnings("unchecked")
    private RemoteService getService(Class serviceClass) {
        
        return (RemoteService) getInjector().getInstance(serviceClass);
    }
}
